package sk.robocup.dvanastyhrac.actionfactories;

import java.util.LinkedList;
import robocup.component.ControllerNumbers.TEAM;
import robocup.component.actions.AttentionToAction;
import robocup.component.tactics.AbstractState;
import robocup.component.worldobjects.Player;

/**
 * Factory vypocitava attention to action
 * @author polak.marek
 */
public class AttentionToActionFactory12 {

    private static final double MAX_DISTANCE = 20.0; //metrov

    //utocnici 6,9,10,11,8 je to tu natvrdo, zislo by sa zmenit podla formacii
    private static int[] attackers = {6, 9, 10, 11, 8};
    // LEFT_MIDFIELD, RIGHT_MIDFIELD, LEFT_ATTACKER, CENTER_ATTACKER, RIGHT_ATTACKER
    private static int[] defenders = {2, 3, 4, 5, 7};
    // LEFT_BACK_FOUR, INLE_BACK_FOUR, INRE_BACK_FOUR, RIGHT_BACK_FOUR, CENTER_MIDFIELD,

    /* Logika AtA :
     *   - ak ma nas tim loptu a vzdialenost < %DISTANCE%, potom:
     *       -vrat zoznam hracov ktory su pri lopte
     *       + vrat hraca ktory je najblizsie (ak taky existuje, inak vrat najrychlejsieho k lopte)
     *       + nastav na neho AtA (ak je AtA nastavene na seba sameho, AtA = null)
     *       - ak je lopta od hraca vo vacsej vzdialenosti ako >%DISTANCE%
     *         potom vyber defaultne
     *   - inak vyber defaultne
     */
    public static AttentionToAction getAttentionToAction(AbstractState state) {
        AttentionToAction ata = null;


        //ak sme si isti kde je lopta
        if (state.getWorld().getBallRef().isReliable()) {

            if (state.getProphet().inPossessionOfBall() == TEAM.WE &&
                    state.getWorld().getSelfRef().getDistance(state.getBall()) < AttentionToActionFactory12.MAX_DISTANCE) {

                //usporiadany zoznam hracov podla vzdialenosti k lopte
                LinkedList<Player> playersInKickDistance = state.getProphet().getPlayersThatCanKick();

                //hrac na ktoreho bude upriamena pozornost
                Player theOne;


                //ak list nieje prazdny
                if (playersInKickDistance.size() != 0) {
                    theOne = playersInKickDistance.getFirst();
                } else //vyber najblizsieho k lopte
                {
                    theOne = state.getProphet().getFastestTeammateToBall();
                }



                //vyber prveho a nastav na neho AtA ak to nie som ja
                if (!theOne.isMe()) {
                    ata = new AttentionToAction(
                            theOne, state.getWorld().getTeamName());
                }

            }


        //ak nevieme kde je lopta tak vzdy pocuvame podla cisiel hracov, obrancovia na obrancov utocnici na utocnikov
        // mozno zapocujeme driblujuceho hraca a ziskame info o lopte ktora nam stale unika
        } else {

            //hrac na ktoreho bude upriamena pozornost
            Player theOne = null;

            //ak som utocnik tak sa zameriavaj na utocnikov
            if (isAttacker(state.getWorld().getSelfRef())) {
                theOne = state.getWorld().getPlayerByNumber(attackers[state.getWorld().getCycle() % attackers.length], true);

            //ak som obranca tak sa zameriavaj na obrancov
            } else if (isDefender(state.getWorld().getSelfRef())) {
                theOne = state.getWorld().getPlayerByNumber(defenders[state.getWorld().getCycle() % defenders.length], true);
            }

            //ak som nasiel hraca na ktoreho sa mam zamerat a nie som to ja, zameriam sa na neho
            if (theOne != null && !theOne.isMe()) {
                ata = new AttentionToAction(
                        theOne, state.getWorld().getTeamName());
            }
        }

        //return computed attention to action 
        return ata;
    }

    /**
     * Metoda vrati ci dany hrac je utocnik
     * @param player hrac
     * @return true ak hrac je utocnik
     */
    private static boolean isAttacker(Player player) {
        for (int playerNumber : attackers) {
            if (player.getNumber() == playerNumber) {
                return true;
            }
        }
        return false;
    }

    /**
     * Metoda vrati ci dany hrac je obranca
     * @param player hrac
     * @return true ak hrac je obranca
     */
    private static boolean isDefender(Player player) {
        for (int playerNumber : defenders) {
            if (player.getNumber() == playerNumber) {
                return true;
            }
        }
        return false;
    }
}
